/**
 * @author Chengzi Xu
 */

package cn.edu.sjtu.stap.sdg.builder;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import cn.edu.sjtu.stap.cfg.ControlFlowGraph;
import cn.edu.sjtu.stap.cfg.builder.ICfgBuilder;
import cn.edu.sjtu.stap.cfg.builder.IntraModuleCfgBuilder;
//import cn.edu.sjtu.stap.cfg.builder.IntraProceduralCfgBuilder;
import cn.edu.sjtu.stap.cg.CallGraph;
import cn.edu.sjtu.stap.cg.builder.ICgBuilder;
import cn.edu.sjtu.stap.sdg.SystemDependenceGraph;

public class DefaultSdgBuilder implements ISdgBuilder {

    private static ISdgBuilder instance = null;

    private CompleteSdgBuilder completeSdgBuilder = new CompleteSdgBuilder();

    private  IntraSdgBuilder intraSdgBuilder = new IntraSdgBuilder();

    public void buildInterSdg(ICgBuilder cgBuilder, ICfgBuilder cfgBuilder) {
        Map<AbstractMethodDeclaration, CallGraph> cgs = cgBuilder.getResult();
        Map<AbstractMethodDeclaration, ControlFlowGraph> cfgs = cfgBuilder
                .getIntraModuleCfgs();
        Map<AbstractMethodDeclaration, SystemDependenceGraph> sdgs = getIntraSdgs();
        Set<AbstractMethodDeclaration> mainCfgMethods = cgBuilder.getProgramEntries();
//        List<AbstractMethodDeclaration> mainCfgMethods = intraProceduralCfgBuilder.getMainMethods();
        Iterator<AbstractMethodDeclaration> i = mainCfgMethods.iterator();
        while (i.hasNext()) {
            AbstractMethodDeclaration main = i.next();
            CallGraph cg = cgs.get(main);
            if (null == cg) {
                return;
            } else {
                cg = CallGraph.getSubCallGraph(cg.getRoot());
            }
            completeSdgBuilder.buildSdg(cg, cfgs, sdgs, main);
        }
    }

    public void buildIntraSdg(ICfgBuilder cfgBuilder) {
        Map<AbstractMethodDeclaration, ControlFlowGraph> cfgs = cfgBuilder
                .getIntraModuleCfgs();
        intraSdgBuilder.buildIntraSdg(cfgs);
    }

    public static ISdgBuilder getInstance() {
        if (instance == null) {
            instance = new DefaultSdgBuilder();
        }
        return instance;
    }

    public Map<AbstractMethodDeclaration, SystemDependenceGraph> getSdgs() {
        return completeSdgBuilder.getResults();
    }

    public Map<AbstractMethodDeclaration, SystemDependenceGraph> getIntraSdgs() {
        return intraSdgBuilder.getResults();
    }

}
